﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Drawing.Drawing2D;

namespace VoltcraftControlInterface
{
    public partial class VoltageLooper : Form
    {
        private MainForm mainform = null;
        public VoltageLooper(Form f1ref)
        {
            InitializeComponent();
            mainform = f1ref as MainForm;
            SerialPort ComPort = new SerialPort();
            string[] ArrayComPortsNames = null;
            int index = -1;
            string ComPortName = null;

            ArrayComPortsNames = SerialPort.GetPortNames();
            do
            {
                index += 1;
                comList.Items.Add((ArrayComPortsNames[index]));
                //rtbIncoming.Text += ArrayComPortsNames[index] + "\n";
            }
            while (!((ArrayComPortsNames[index] == ComPortName) ||
                                (index == ArrayComPortsNames.GetUpperBound(0))));
            if (index == ArrayComPortsNames.GetUpperBound(0))
            {
                ComPortName = ArrayComPortsNames[0];
            }
            comList.Text = ArrayComPortsNames[0];
        }
        string ReplaceFirst(string text, string search, string replace)
        {
            int pos = text.IndexOf(search);
            if (pos < 0)
            {
                return text;
            }
            return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
        }
        public string WriteAndRead(string towrite)
        {
            int btoread = VoltPort.BytesToRead;
            string outstring = "";
            Byte[] waste = new Byte[btoread];
            VoltPort.Read(waste, 0, btoread);
            VoltPort.Write(towrite);
            Thread.Sleep(25);
            bool loopstat = true;
            int loopcount = 0;
            string appstring = "";
            while (loopstat)
            {
                btoread = VoltPort.BytesToRead;
                char[] returnbuff = new char[btoread];
                VoltPort.Read(returnbuff, 0, btoread);
                string retstring = new string(returnbuff);
                appstring = appstring + retstring;
                if (appstring.Contains("OK\r"))
                {
                    appstring = ReplaceFirst(appstring, "OK\r", "");
                    outstring = appstring;
                    loopstat = false;
                }
                if (retstring == "")
                {
                    loopcount++;
                }
                if (loopcount > 100)
                {
                    outstring = appstring;
                    loopstat = false;
                }
                if (loopstat) Thread.Sleep(2);
            }
            return outstring;
        }
        public SerialPort VoltPort;
        private void v1Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v1Slide.Value;
            v1Box.Value = val / 10;
        }

        private void v1Box_ValueChanged(object sender, EventArgs e)
        {
            v1Slide.Value = (int)(v1Box.Value * 10);
        }

        private void v2Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v2Slide.Value;
            v2Box.Value = val / 10;
        }

        private void v3Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v3Slide.Value;
            v3Box.Value = val / 10;
        }

        private void v4Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v4Slide.Value;
            v4Box.Value = val / 10;
        }

        private void v5Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v5Slide.Value;
            v5Box.Value = val / 10;
        }

        private void v6Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v6Slide.Value;
            v6Box.Value = val / 10;
        }

        private void v7Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v7Slide.Value;
            v7Box.Value = val / 10;
        }

        private void v8Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v8Slide.Value;
            v8Box.Value = val / 10;
        }

        private void v9Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v9Slide.Value;
            v9Box.Value = val / 10;
        }

        private void v10Slide_Scroll(object sender, EventArgs e)
        {
            Decimal val = v10Slide.Value;
            v10Box.Value = val / 10;
        }

        private void v2Box_ValueChanged(object sender, EventArgs e)
        {
            v2Slide.Value = (int)(v2Box.Value * 10);
        }

        private void v3Box_ValueChanged(object sender, EventArgs e)
        {
            v3Slide.Value = (int)(v3Box.Value * 10);
        }

        private void v4Box_ValueChanged(object sender, EventArgs e)
        {
            v4Slide.Value = (int)(v4Box.Value * 10);
        }

        private void v5Box_ValueChanged(object sender, EventArgs e)
        {
            v5Slide.Value = (int)(v5Box.Value * 10);
        }

        private void v6Box_ValueChanged(object sender, EventArgs e)
        {
            v6Slide.Value = (int)(v6Box.Value * 10);
        }

        private void v7Box_ValueChanged(object sender, EventArgs e)
        {
            v7Slide.Value = (int)(v7Box.Value * 10);
        }

        private void v8Box_ValueChanged(object sender, EventArgs e)
        {
            v8Slide.Value = (int)(v8Box.Value * 10);
        }

        private void v9Box_ValueChanged(object sender, EventArgs e)
        {
            v9Slide.Value = (int)(v9Box.Value * 10);
        }

        private void v10Box_ValueChanged(object sender, EventArgs e)
        {
            v10Slide.Value = (int)(v10Box.Value * 10);
        }

        private void selectBtn_Click(object sender, EventArgs e)
        {
            if (!mainform.IsOpen())
            {
                mainform.disableOpen();
                comList.Enabled = false;
                selectBtn.Enabled = false;
                VoltPort = new SerialPort(comList.Text, 9600, Parity.None, 8, StopBits.One);
                VoltPort.Handshake = Handshake.None;
                VoltPort.WriteTimeout = 2000;
                try
                {
                    VoltPort.Open();
                    closeBtn.Enabled = true;
                    controlsPnl.Enabled = true;
                    interv1Box.Enabled = true;
                    interv2Box.Enabled = true;
                    runBtn.Enabled = true;
                }
                catch
                {
                    MessageBox.Show("Error while opening COM port!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    VoltPort.Close();
                    comList.Enabled = true;
                    selectBtn.Enabled = true;
                    closeBtn.Enabled = false;
                    controlsPnl.Enabled = false;
                    interv1Box.Enabled = false;
                    interv2Box.Enabled = false;
                    runBtn.Enabled = false;
                    mainform.enableOpen();
                }
            }
        }

        private void closeBtn_Click(object sender, EventArgs e)
        {
            shouldstop = true;
            if (updthread != null)
            {
                if (updthread.IsAlive)
                {
                    updthread.Abort();
                }
            }
            VoltPort.Close();
            comList.Enabled = true;
            selectBtn.Enabled = true;
            closeBtn.Enabled = false;
            controlsPnl.Enabled = false;
            interv1Box.Enabled = false;
            interv2Box.Enabled = false;
            runBtn.Enabled = false;
            mainform.enableOpen();
        }
        private volatile bool shouldstop;
        Thread updthread;
        delegate void SetFixedCallback(Decimal value);
        private void SetFixedBoxValue(Decimal value)
        {
            if (this.fixednumBox.InvokeRequired)
            {
                SetFixedCallback d = new SetFixedCallback(SetFixedBoxValue);
                Invoke(d, new object[] { value });
            }
            else
            {
                this.fixednumBox.Value = this.fixednumBox.Value - value;
            }
        }
        delegate void SetTimeCallback(Decimal ltime);
        private void SetTimeBoxValue(Decimal ltime)
        {
            if (this.minutesBox.InvokeRequired)
            {
                SetTimeCallback d = new SetTimeCallback(SetTimeBoxValue);
                Invoke(d, new object[] { ltime });
            }
            else
            {
                if (ltime < 0)
                {
                    minutesBox.Value = 0;
                } else this.minutesBox.Value = ltime;
            }
        }
        delegate void OpEndedCallback();
        private void OpEnded()
        {
            if (this.runBtn.InvokeRequired)
            {
                OpEndedCallback d = new OpEndedCallback(OpEnded);
                Invoke(d, new object[] {  });
            }
            else
            {
                runBtn.Enabled = true;
                stopBtn.Enabled = false;
                controlsPnl.Enabled = true;
            }
        }
        public void WriteVolts(Decimal volt)
        {
            volt = volt * 10;
                if (volt < 10)
                {
                    WriteAndRead("VOLT00" + volt.ToString("F0") + "\r");
                }
                else if (volt < 100)
                {
                    WriteAndRead("VOLT0" + volt.ToString("F0") + "\r");
                }
                else
                {
                    WriteAndRead("VOLT" + volt.ToString("F0") + "\r");
                }
        }
        public void StartCycle()
        {
            shouldstop = false;
            Stopwatch loopTime = new Stopwatch();
            if (timedRb.Checked)
            {
                double maxminutes = (double)minutesBox.Value;
                loopTime.Start();
                while (loopTime.Elapsed.TotalMinutes < maxminutes)
                {
                    try
                    {
                        if (checkBox1.Checked)
                        {
                            WriteVolts(v1Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox2.Checked)
                        {
                            WriteVolts(v2Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox3.Checked)
                        {
                            WriteVolts(v3Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox4.Checked)
                        {
                            WriteVolts(v4Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox5.Checked)
                        {
                            WriteVolts(v5Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox6.Checked)
                        {
                            WriteVolts(v6Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox7.Checked)
                        {
                            WriteVolts(v7Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox8.Checked)
                        {
                            WriteVolts(v8Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox9.Checked)
                        {
                            WriteVolts(v9Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox10.Checked)
                        {
                            WriteVolts(v10Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                    }
                    catch
                    {
                        break;
                    }
                    Thread.Sleep((int)interv2Box.Value);
                    SetTimeBoxValue((decimal)(maxminutes-loopTime.Elapsed.TotalMinutes));
                    if (shouldstop) break;
                }
            } else if (fixedRb.Checked)
            {
                int endval = (int)fixednumBox.Value;
                for (int i = 1; i <= endval; i++)
                {
                    try
                    {
                        if (checkBox1.Checked)
                        {
                            WriteVolts(v1Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox2.Checked)
                        {
                            WriteVolts(v2Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox3.Checked)
                        {
                            WriteVolts(v3Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox4.Checked)
                        {
                            WriteVolts(v4Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox5.Checked)
                        {
                            WriteVolts(v5Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox6.Checked)
                        {
                            WriteVolts(v6Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox7.Checked)
                        {
                            WriteVolts(v7Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox8.Checked)
                        {
                            WriteVolts(v8Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox9.Checked)
                        {
                            WriteVolts(v9Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox10.Checked)
                        {
                            WriteVolts(v10Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                    }
                    catch
                    {
                        break;
                    }
                    Thread.Sleep((int)interv2Box.Value);
                    SetFixedBoxValue(1);
                    if (shouldstop) break;
                }
            } else if (loopRb.Checked)
            {
                while (!shouldstop)
                {
                    try
                    {
                        if (checkBox1.Checked)
                        {
                            WriteVolts(v1Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox2.Checked)
                        {
                            WriteVolts(v2Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox3.Checked)
                        {
                            WriteVolts(v3Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox4.Checked)
                        {
                            WriteVolts(v4Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox5.Checked)
                        {
                            WriteVolts(v5Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox6.Checked)
                        {
                            WriteVolts(v6Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox7.Checked)
                        {
                            WriteVolts(v7Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox8.Checked)
                        {
                            WriteVolts(v8Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox9.Checked)
                        {
                            WriteVolts(v9Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                        if (checkBox10.Checked)
                        {
                            WriteVolts(v10Box.Value);
                            Thread.Sleep((int)interv1Box.Value);
                        }
                    }
                    catch
                    {
                        break;
                    }
                    Thread.Sleep((int)interv2Box.Value);
                }
            }
            OpEnded();
        }
        public void StopCycle()
        {
            shouldstop = true;
        }
        private void runBtn_Click(object sender, EventArgs e)
        {
            if (checkBox1.Checked || checkBox2.Checked || checkBox3.Checked || checkBox4.Checked || checkBox5.Checked || checkBox6.Checked || checkBox7.Checked || checkBox8.Checked || checkBox9.Checked || checkBox10.Checked)
            {
                runBtn.Enabled = false;
                stopBtn.Enabled = true;
                controlsPnl.Enabled = false;
                updthread = new System.Threading.Thread(new System.Threading.ThreadStart(this.StartCycle));
                updthread.Start();
            }
            //while (!updthread.IsAlive);
            /*runBtn.Enabled = true;
            stopBtn.Enabled = false;
            controlsPnl.Enabled = true;*/
        }

        private void stopBtn_Click(object sender, EventArgs e)
        {
            StopCycle();
            runBtn.Enabled = true;
            stopBtn.Enabled = false;
            controlsPnl.Enabled = true;
        }

        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (closeBtn.Enabled)
            {
                VoltPort.Close();
                comList.Enabled = true;
                selectBtn.Enabled = true;
                closeBtn.Enabled = false;
                controlsPnl.Enabled = false;
                interv1Box.Enabled = false;
                interv2Box.Enabled = false;
                runBtn.Enabled = false;
                mainform.enableOpen();
            }
        }

        private void VoltageLooper_Paint(object sender, PaintEventArgs e)
        {
            using (LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle,
                                                               Color.White,
                                                               Color.LightGray,
                                                               90F))
            {
                e.Graphics.FillRectangle(brush, this.ClientRectangle);
            }
        }
    }
}
